import static org.junit.Assert.assertTrue;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Runner {
	private final static int MAX_NUMBER = 128;
	private final static int CYCLES = 1024 * 128;

	protected static Computable<Integer, int[]> factorizator;
	protected static ExecutorService executor;

	private Timer timer = new Timer();

	public void initFactorizator() {
		int[] primes = DKUtil.makeIntArray(DKUtil.generatePrimes(MAX_NUMBER));
		factorizator = new CachedComputable1<>(new Factorizator(primes));
	}

	public Runnable newTask() {
		return new Runnable() {
			public void run() {
				try {
					factorizator
							.compute((int) (Math.random() * MAX_NUMBER * 100));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
	}

	@Before
	public void initExecutor() {
		executor = Executors.newFixedThreadPool(1024);
	}

	@After
	public void checkResults() throws InterruptedException {
		waitFor();
	}

	@Test
	public void test() {
		initFactorizator();
		timer.start();
		for (int i = 0; i < CYCLES; i++) {
			executor.submit(newTask());
		}
	}

	protected void waitFor() throws InterruptedException {
		executor.shutdown();
		boolean terminated = executor.awaitTermination(Long.MAX_VALUE,
				TimeUnit.SECONDS);
		timer.printSeconds();
		assertTrue("Finished all tasks.", terminated);
	}
}
